package com.toocms.jinjuhang.config

import android.content.Context
import com.toocms.jinjuhang.data.system.Region3dData
import com.toocms.jinjuhang.data.system.RegionItemData
import com.toocms.tab.network.ApiTool
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.lang.ref.SoftReference
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

object Region {
    private const val effectiveTimeConstant = 2 * 24 * 60 * 60 * 1000L //有效时长
    private const val localRegionName = "Region.log"
    private const val localRegionPath = "log/${localRegionName}"
    private val executorService: ExecutorService = Executors.newSingleThreadExecutor()
    private var context: Context? = null

    @Volatile
    private var _localRegion: SoftReference<LocalRegion>? = null
    val localRegion: LocalRegion?
        get() {
            val result = _localRegion?.get()
            if (null == result && null != context) {
                init(context!!)
            }
            return result
        }

    fun init(context: Context) {
        this.context = context.applicationContext
        //获取存放地址的本地文件
        val localRegionFile = localFile(this.context)
        //判断本地文件是否存在
        if (null == localRegionFile || !localRegionFile.exists()) {
            //不存在，同步后台的地址
            update()
        } else {
            //存在，读取本地的地址
            readLocalRegion(localRegionFile)
        }
    }

    /**
     * 存放地址的本地文件
     */
    private fun localFile(context: Context?): File? {
        if (null == context) return null
        val rootFile = this.context!!.filesDir
        val localRegionFile = File(rootFile, localRegionPath)
        val localRegionFileParentDir = File(localRegionFile.parent)
        if (!localRegionFileParentDir.exists()) {
            localRegionFileParentDir.mkdirs()
        }
        return localRegionFile
    }

    /**
     * 读取本地地址
     */
    private fun readLocalRegion(file: File) {
        executorService.submit {
            val inputStream = ObjectInputStream(FileInputStream(file))
            try {
                var region: LocalRegion? = inputStream.readObject() as LocalRegion
                inputStream.close()
                _localRegion = SoftReference(region)
                //检测是否更新本地文件
                checkUpdate()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }

    /**
     * 写入本地文件
     */
    private fun whiteLocalRegion(file: File, localRegion: LocalRegion) {
        executorService.submit {
            val outputStream = ObjectOutputStream(FileOutputStream(file))
            try {
                outputStream.writeObject(localRegion)
                //检测是否更新本地文件
            } catch (e: IOException) {
                e.printStackTrace()
            } finally {
                outputStream.close()
            }
        }
    }


    /**
     * 检测是否同步网络地址
     */
    private fun checkUpdate() {
        var region = _localRegion?.get()
        //判断地址是否为空
        if (null == region) {
            //为空，同步后台的地址
            update()
            return
        }
        //不为空
        //比较更新时间（有效时间<当前时间-上次更新时间）
        if (effectiveTimeConstant < System.currentTimeMillis() - region.updateTime) {
            //同步后台的地址
            update()
        }
    }

    /**
     * 后台获取的地址转成本地地址
     */
    private fun webRegion2localRegion(webRegion: Region3dData): LocalRegion {
        val updateTime = System.currentTimeMillis()
        val province = ArrayList<RegionItemData>()
        val city = ArrayList<List<RegionItemData>>()
        val district = ArrayList<List<List<RegionItemData>>>()
        webRegion.list?.forEach { provinceItem ->
            province += provinceItem.copy(
                id = provinceItem.id,
                region_name = provinceItem.region_name,
                parent_id = provinceItem.parent_id
            )
            val provinceCityItem = ArrayList<RegionItemData>()
            val provinceDistrictItem = ArrayList<List<RegionItemData>>()
            provinceItem._child?.forEach { cityItem ->
                provinceCityItem += cityItem.copy(
                    id = cityItem.id,
                    region_name = cityItem.region_name,
                    parent_id = cityItem.parent_id
                )
                provinceDistrictItem += cityItem._child ?: ArrayList<RegionItemData>()
            }
            city += provinceCityItem
            district += provinceDistrictItem
        }
        return LocalRegion(updateTime, province, city, district)
    }


    /**
     * 同步后台的地址
     */
    private fun update() {
        ApiTool.post(Urls.System.REGION_3D)
            .asTooCMSResponse(Region3dData::class.java)
            .observeOn(AndroidSchedulers.mainThread())
            .request {
                //获取本地地址
                var localRegion: LocalRegion? = webRegion2localRegion(it)
                this._localRegion = SoftReference(localRegion)
                //写入本地文件
                var localFile = localFile(context)
                if (null != localFile) {
                    whiteLocalRegion(localFile, localRegion!!)
                }
            }
    }


}

data class LocalRegion(
    val updateTime: Long = 0L,
    val province: List<RegionItemData>?,
    val city: List<List<RegionItemData>>?,
    val district: List<List<List<RegionItemData>>>?
) : java.io.Serializable
